package com.pj.project.sys_user_acc;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.pj.project.aliyun_config.AliyunConfig;
import com.pj.project.aliyun_config.AliyunConfigMapper;
import com.pj.utils.CaptchaRedisUtil;
import com.pj.utils.SspClientBrdUtil;
import com.pj.utils.cache.RedisUtil;
import com.pj.utils.so.SoMap;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.open.api.WxOpenMpService;
import me.chanjar.weixin.open.api.WxOpenService;
import me.chanjar.weixin.open.api.impl.WxOpenMpServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import com.pj.current.satoken.StpUserUtil;
import com.pj.project.sys_user.SysUser;
import com.pj.project.sys_user.SysUserUtil;
import com.pj.project.sys_user_sync.brd.SspServerBrdUtil;
import com.pj.project4sp.config.SpConfigUtil;
import com.pj.utils.VcUtil;
import com.pj.utils.sg.AjaxError;
import com.pj.utils.sg.AjaxJson;
import com.pj.utils.sg.NbUtil;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * 用户模块，有关验证码的相关操作UserMapper.xml
 * UserMapper
 * @author kong
 */
@RestController
@RequestMapping("/SysUserAcc/")
@Slf4j
public class SysUserAccController {

    @Autowired
    SysUserAccMapper sysUserAccMapper;

    @Autowired
    SysUserAccService sysUserAccService;

    @Autowired
    WxMpService wxMpService;

    @Autowired
    WxOpenService wxOpenService;

    @Autowired
    AliyunConfigMapper aliyunConfigMapper;

    // -------------------------- 登录相关 --------------------------

    /** 验证码登录 -> 发送验证码 */
    @RequestMapping("loginByPhone_sendVc")
    AjaxJson loginByPhone_sendVc(String phone) {
        // 获取短信配置
        AliyunConfig aliyunConfig = aliyunConfigMapper.getById(1L);
        String smsString = JSON.toJSON(aliyunConfig).toString();
        VcUtil.send(VcUtil.USER_LOGIN, phone,smsString);
        return AjaxJson.getSuccess();
    }

    /** 验证码登录 -> 确认 */
    @RequestMapping("loginByPhone_ok")
	@Transactional(rollbackFor = Exception.class)	
    AjaxJson loginByPhone_ok(String phone, String vc, String openid, String unionId) {
        // 先验证
        VcUtil.check(VcUtil.USER_LOGIN, phone, vc);
        
        // 检查登录信息
        boolean isNew = false; // 此变量含义：该手机号是否为首次登录 
        SysUserAcc userAcc = sysUserAccMapper.getByPhone(phone);
        if(userAcc == null) {
        	// 如果查询不到，则直接自动注册一个  
        	// 先检查系统配置是否允许注册 
        	if(SpConfigUtil.isAllowRegister() == false) {
        		return AjaxJson.getError("登录失败：系统暂未开放注册新用户，如有疑问，请联系网站管理员");
        	}
        	
        	// 开始注册
        	userAcc = sysUserAccService.regByPhone(phone,openid, unionId);
        	isNew = true;
        }else if(!StringUtils.isEmpty(openid)){
            int i = sysUserAccService.updateOpenId(phone, openid, unionId);
        }
        
		// 账号能否登录的判断 
        if(userAcc.getStatus() == 2) {
		    AjaxError.throwMsg("此账号已被禁用，如有疑问，请联系平台管理员");
		}
        
        // 登录成功后删除验证码 
        VcUtil.delete(VcUtil.USER_LOGIN, phone);
        
        if(isNew) {
    		// $$ 向外广播
    		SysUser s2 = SysUserUtil.sysUserMapper.getByPhone(phone);
            SspServerBrdUtil.userAdd(s2, null);
        }

        // 返回信息 
        return successLoginInfo(userAcc.getId()).set("isNew", isNew);
    }

    /**
     * 获取验证码，并将验证码存储到 Redis
     */
    @RequestMapping("code")
    public AjaxJson getRedirectUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {
        Map<String, String> resultMap = new HashMap<>();

        // 调用工具类获取验证码信息
//        CaptchaRedisUtil util = new CaptchaRedisUtil();
        CaptchaRedisUtil.CaptchaInfo captchaInfo = CaptchaRedisUtil.generateCaptcha();

        // 将验证码图片和验证码存储键返回给前端
        resultMap.put("captchaImage", captchaInfo.getCaptchaImage());
        resultMap.put("captchaKey", captchaInfo.getCaptchaKey());

        return AjaxJson.getSuccessData(resultMap);
    }


    /** 小程序授权直接登录 */
    @RequestMapping("doLoginApplet")
    AjaxJson doLoginApplet(String phone) {
        // 校验参数 
    	if(NbUtil.hasNull(phone)) {
    		return AjaxJson.getError("请输入");
    	}

        // 获取相应用户
        SysUserAcc userAcc = sysUserAccService.doLoginApplet(phone);
        AjaxJson ajaxJson = successLoginInfo(userAcc.getId());
        // 返回信息 
        return ajaxJson;
    }


    /** id/昵称/手机号/邮箱 + 密码登录 */
    @RequestMapping("doLogin")
//    AjaxJson doLogin(String name, String pwd, String captchaCode, String userInputCaptcha) {
    AjaxJson doLogin(String name, String pwd) {

        // 校验参数
        if(NbUtil.hasNull(name, pwd)) {
            return AjaxJson.getError("请输入");
        }

        // 验证验证码
        /*boolean captchaValid = CaptchaRedisUtil.verifyCaptcha(captchaCode, userInputCaptcha);

        if (!captchaValid) {
            return AjaxJson.getError("验证码错误");
        }
*/
        // 获取相应用户
        SysUserAcc userAcc = sysUserAccService.doLogin(name, pwd);
        AjaxJson ajaxJson = successLoginInfo(userAcc.getId());
        // 返回信息
        return ajaxJson;
    }


    //微信登录 获取二维码
    @PostMapping("/wechat/login")
    public AjaxJson webAuthorize(HttpServletRequest request, HttpServletResponse response) throws IOException{
        String url = request.getParameter("url");
        // 构建重定向URL并带有查询参数
        String redirectUrl = UriComponentsBuilder.fromUriString(SspClientBrdUtil.WECHAT_PC)
                .queryParam("appid", SspClientBrdUtil.appid)
                .queryParam("scope", "snsapi_login")
                .queryParam("redirect_uri",SspClientBrdUtil.REDIRECT_URL)
                .queryParam("state",getRealState(UUID.fastUUID().toString()))
                .queryParam("url",url)
                .toUriString();
        response.sendRedirect(redirectUrl);
        return AjaxJson.getSuccessData(redirectUrl);
    }

    //微信登陆 回调地址
    @GetMapping("/wechat/callback")
    public void callBack(String code, String url, HttpServletResponse response) throws IOException {
        try {
            // 构建重定向URL并带有查询参数
            String redirectUrl = UriComponentsBuilder.fromUriString(url)
                    .queryParam("code",code)
                    .queryParam("client","ssp-client3")
//                    .queryParam("redirect","http://172.168.1.127:9002/unifiedLogin?client=ssp-client3&redirect=http://172.168.1.127:10000/sso-login?back=http://172.168.1.127:10000/login")
                    .queryParam("redirect",url)
                    .toUriString();
            response.sendRedirect(redirectUrl);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }


    /** 微信扫码登录 */
    @RequestMapping("doLoginWechat")
    AjaxJson doLoginWechat(String code) {
        // 校验参数
        if(NbUtil.hasNull(code)) {
            return AjaxJson.getError("无code");
        }

        // 获取 openid
        try {
            WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(SspClientBrdUtil.appid, SspClientBrdUtil.appsecret, code);
            log.info("wxOAuth2AccessToken->"+wxOAuth2AccessToken);
            WxOAuth2UserInfo wxUser = wxMpService.getOAuth2Service().getUserInfo(wxOAuth2AccessToken, null);
            log.info("wxUser->"+wxUser);

            String openId = wxOAuth2AccessToken.getOpenId();
            String unionId = wxOAuth2AccessToken.getUnionId();

            SysUserAcc byOpenId = sysUserAccMapper.getByOpenId(openId);
            if(byOpenId==null){     //根据openid查询不到该用户，则让其绑定手机号
                SoMap mapo = new SoMap();
                mapo.set("openid",openId);
                mapo.set("unionId",unionId);
                return AjaxJson.getSuccessData(mapo);
            }

            //认证中心系统登录逻辑
            SysUserAcc sysUserAcc = sysUserAccService.doLoginWechat(wxUser);
            AjaxJson ajaxJson = successLoginInfo(sysUserAcc.getId());

            return AjaxJson.getSuccessData(ajaxJson);
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            return AjaxJson.getError(e.getMessage());
        }


    }


    /**
     * 获取state，如果为空， 则默认取当前日期的时间戳
     *
     * @param state 原始的state
     * @return 返回不为null的state
     */
    protected String getRealState(String state) {
        if (StringUtils.isEmpty(state)) {
            state = UUID.randomUUID().toString();
        }
        /* 缓存state 回调时候验证缓存里是否有state，如果没有的话则代表是非法访问*/
        RedisUtil.setBySECONDS(state, state, 600L);
        return state;
    }




    /** 注销登录 */
	@RequestMapping("doExit")
	AjaxJson doExit() {
		StpUserUtil.logout();
		return AjaxJson.getSuccess();
	}

    // 返回指定账号登录信息 
    private AjaxJson successLoginInfo(long userId) {

        // 调用 Sa-Token 登录会话 
        StpUserUtil.login(userId);    
        
        // 将User对象写入User-Session，以便所有Client端可以取到 
        Object user = SysUserAccUtil.getUserById(userId);
        StpUserUtil.getSession().set("user", user);


        // 组织返回参数
        SoMap map = new SoMap();
        map.put("userId", userId);
        map.put("user", user);
        map.put("tokenInfo", StpUtil.getTokenInfo());
        return AjaxJson.getSuccessData(map);

        // 返回账号数据 
//		return AjaxJson.getSuccess()
//                .set("userId", userId)     // 用户id
//                .set("user", user)    // 用户信息
//                .set("tokenInfo", StpUserUtil.getTokenInfo());  // token信息
	}
  
}
